home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / wasm223.zip / SERIAL1.ASM < prev    next >
Assembly Source File  |  1993-05-04  |  15KB  |  494 lines

  1. ;**********************************;
  2. ; WASM Serial I/O, Basic Routines  ;
  3. ; By Eric Tauck                    ;
  4. ;                                  ;
  5. ; Defines:                         ;
  6. ;                                  ;
  7. ;   ComBuf  assign local buffer    ;
  8. ;   ComAll  allocate buffer        ;
  9. ;   ComRel  release buffer         ;
  10. ;   ComOpn  open serial port       ;
  11. ;   ComClo  close serial port      ;
  12. ;   ComClr  clear buffer           ;
  13. ;   ComByt  return bytes in buffer ;
  14. ;   ComGet  input a byte           ;
  15. ;   ComPut  output a byte          ;
  16. ;                                  ;
  17. ; Requires:                        ;
  18. ;                                  ;
  19. ;   MEMORY.ASM                     ;
  20. ;**********************************;
  21.  
  22.         jmp     _serial1_end
  23.  
  24. PARITY_NONE     EQU     0       ;no parity
  25. PARITY_ODD      EQU     1       ;odd parity
  26. PARITY_EVEN     EQU     2       ;even parity
  27.  
  28. ;--- serial port interrupt data
  29.  
  30. _COM_PIC01      EQU     21H     ;8259 programable interrupt controller
  31. _COM_PIC00      EQU     20H     ;"        "          "         "
  32. _COM_EOI        EQU     20H     ;end of interrupt command
  33.  
  34. ;--- line status register values
  35.  
  36. _COM_XMITREADY  EQU     20h
  37.  
  38. ;--- modem control register values
  39.  
  40. _COM_DTR        EQU     1
  41. _COM_RTS        EQU     2
  42. _COM_OUT2       EQU     8
  43.  
  44. ;--- interrupt enable register signals
  45.  
  46. _COM_DATAREADY  EQU     1
  47.  
  48. ;--- modem initialization bits
  49.  
  50. _COM_DIVLATCH   EQU     80H     ;divlatch bit value
  51. _COM_PARSHIFT   EQU     3       ;parity bit shift
  52. _COM_STOPSHIFT  EQU     2       ;stop bit shift
  53. _COM_WORDSHIFT  EQU     0       ;word bit shift
  54.  
  55. ;--- commmunications record offsets
  56.  
  57. _COM_PORT       EQU     0       ;port number
  58. _COM_BUFBEG     EQU     1       ;buffer begin address
  59. _COM_BUFEND     EQU     5       ;buffer end offset
  60. _COM_BUFPTR1    EQU     7       ;current buffer write address
  61. _COM_BUFPTR2    EQU     11      ;current buffer read address
  62. _COM_BUFSIZE    EQU     15      ;input buffer size
  63. _COM_BUFBYTE    EQU     17      ;bytes in buffer
  64. _COM_INTOLD     EQU     19      ;old interrupt vector
  65. _COM_INTNUM     EQU     23      ;interrupt number
  66. _COM_INTMSK     EQU     24      ;interrupt enable/disable mask
  67. _COM_TXDATA     EQU     25      ;transmit data
  68. _COM_RXDATA     EQU     27      ;receive data
  69. _COM_DIVLSB     EQU     29      ;baud rate divisor lsb
  70. _COM_DIVMSB     EQU     31      ;baud rate divisor msb
  71. _COM_INTENABLE  EQU     33      ;interrupt enable
  72. _COM_INTIDENT   EQU     35      ;interrupt identification
  73. _COM_LINECTL    EQU     37      ;line control
  74. _COM_MODEMCTL   EQU     39      ;modem control
  75. _COM_LINESTAT   EQU     41      ;line status
  76. _COM_MODEMSTAT  EQU     43      ;modem status
  77.  
  78. SERIAL_RECORD   EQU     45      ;bytes in serial port record
  79.  
  80. ;--- interrupt data pointers
  81.  
  82. _com_data0B     LABEL   DWORD
  83.                 DW      ?, ?
  84.  
  85. _com_data0C     LABEL   DWORD
  86.                 DW      ?, ?
  87.  
  88. ;========================================
  89. ; Communications interrupt handlers.
  90.  
  91. _Com_Int0B      LABEL   NEAR    ;entry point for interrupt 11
  92.         push    bx
  93.         push    ds
  94.         seg     cs
  95.         lds     bx, _Com_Data0B
  96.         jmps    _cmint1
  97.  
  98. _Com_Int0C      LABEL   NEAR    ;entry point for interrupt 12
  99.         push    bx
  100.         push    ds
  101.         seg     cs
  102.         lds     bx, _Com_Data0C
  103.  
  104. _cmint1 push    ax
  105.         push    dx
  106.         push    di
  107.         push    es
  108.  
  109.         mov     al, _COM_EOI            ;end of interrupt
  110.         out     _COM_PIC00, al          ;send to controller
  111.  
  112. ;--- get byte
  113.  
  114.         mov     dx, [bx + _COM_RXDATA]  ;input port
  115.         in      al, dx                  ;get byte
  116.  
  117. ;--- store byte
  118.  
  119.         les     di, [bx + _COM_BUFPTR1] ;buffer write address
  120.         cmp     di, [bx + _COM_BUFEND]  ;check if at end
  121.         jne     _cmint2
  122.         mov     di, [bx + _COM_BUFBEG]  ;wrap to start
  123. _cmint2 seg     es
  124.         mov     [di], al                ;save byte
  125.         inc     di                      ;increment pointer
  126.         mov     [bx + _COM_BUFPTR1], di ;save pointer
  127.  
  128. ;--- update bytes in buffer
  129.  
  130.         mov     ax, [bx + _COM_BUFBYTE] ;load byte count
  131.         cmp     ax, [bx + _COM_BUFSIZE] ;compare to size
  132.         je      _cmint3                 ;skip increment if full
  133.         inc     WORD [bx+_COM_BUFBYTE]  ;increment bytes
  134.  
  135. ;--- finished
  136.  
  137. _cmint3 pop     es
  138.         pop     di
  139.         pop     dx
  140.         pop     ax
  141.         pop     ds
  142.         pop     bx
  143.         iret
  144.  
  145. ;========================================
  146. ; Assign a local communications buffer.
  147. ;
  148. ; In: BX= record address; AX= buffer
  149. ;     address; CX= size of buffer.
  150.  
  151. ComBuf  PROC    NEAR
  152.         mov     [bx + _COM_BUFBEG + 2], cs      ;segment
  153.         mov     [bx + _COM_BUFBEG], ax          ;buffer base
  154.         mov     [bx + _COM_BUFSIZE], cx         ;buffer size
  155.         add     ax, cx
  156.         mov     [bx + _COM_BUFEND], ax          ;end of buffer
  157.         ret
  158.         ENDP
  159.  
  160. ;========================================
  161. ; Allocate a communications buffer.
  162. ;
  163. ; In: BX= record address; AX= size of
  164. ;     buffer.
  165. ;
  166. ; Out: CY= set if error; AL= error code
  167. ;      if error; DX= memory available (if
  168. ;      out of memory).
  169.  
  170. ComAll  PROC    NEAR
  171.         push    bx
  172.         call    MemAll                          ;allocate memory
  173.         pop     bx
  174.         jc      _cmall1
  175.         mov     [bx + _COM_BUFBEG + 2], ax      ;buffer segment
  176.         mov     WORD [bx + _COM_BUFBEG], 0      ;buffer base
  177.         mov     [bx + _COM_BUFSIZE], dx         ;buffer size
  178.         mov     [bx + _COM_BUFEND], dx          ;end of buffer
  179. _cmall1 ret
  180.         ret
  181.         ENDP
  182.  
  183. ;========================================
  184. ; Release a communications buffer.
  185. ;
  186. ; In: BX= record address.
  187.  
  188. ComRel  PROC    NEAR
  189.         mov     ax, [bx + _COM_BUFBEG + 2]      ;load segment
  190.         mov     dx, cs                          ;current segment
  191.         cmp     ax, dx                          ;check if local buffer
  192.         je      comrel1
  193.         call    MemRel                          ;release memory
  194. comrel1 ret
  195.         ENDP
  196.  
  197. ;========================================
  198. ; Open communications port.
  199. ;
  200. ; In: BX= record address; AL= port (1 or
  201. ;     2); AH= parity; DX= baud; CL= data
  202. ;     bits; CH= stop bits.
  203.  
  204. ComOpn  PROC    NEAR
  205.         push    di
  206.         mov     di, bx
  207.  
  208.         push    dx
  209.         push    ax
  210.  
  211. ;--- get intialization byte
  212.  
  213.         mov     dx, cx
  214.  
  215.         mov     al, _COM_DIVLATCH
  216.  
  217.         mov     cl, _COM_PARSHIFT
  218.         shl     ah, cl
  219.         or      al, ah
  220.  
  221.         mov     cl, _COM_WORDSHIFT
  222.         sub     dl, 5
  223.         shl     dl, cl
  224.         or      al, dl
  225.  
  226.         mov     cl, _COM_STOPSHIFT
  227.         dec     dh
  228.         shl     dh, cl
  229.         or      al, dh
  230.  
  231.         pop     dx              ;restore port number
  232.         push    ax              ;save initialization byte for later
  233.  
  234. ;--- close first if open and clear buffer
  235.  
  236.         push    dx
  237.         mov     bx, di
  238.         call    ComClr                  ;clear buffer
  239.         pop     ax
  240.  
  241. ;--- set port addresses
  242.  
  243.         mov     [di+_COM_PORT], al      ;save port number
  244.         mov     dl, al
  245.         sub     dh, dh
  246.         mov     ax, 003F8h              ;base address
  247.         dec     dx                      ;0 or 1
  248.         mov     cl, 8
  249.         shl     dx, cl
  250.         sub     ax, dx                  ;base port address
  251.  
  252.         mov     [di + _COM_TXDATA], ax
  253.         mov     [di + _COM_RXDATA], ax
  254.         mov     [di + _COM_DIVLSB], ax
  255.         inc     ax
  256.         mov     [di + _COM_DIVMSB], ax
  257.         mov     [di + _COM_INTENABLE], ax
  258.         inc     ax
  259.         mov     [di + _COM_INTIDENT], ax
  260.         inc     ax
  261.         mov     [di + _COM_LINECTL], ax
  262.         inc     ax
  263.         mov     [di + _COM_MODEMCTL], ax
  264.         inc     ax
  265.         mov     [di + _COM_LINESTAT], ax
  266.         inc     ax
  267.         mov     [di + _COM_MODEMSTAT], ax
  268.  
  269. ;--- initialize port
  270.  
  271.         mov     dx, [di + _COM_LINECTL] ;line control port
  272.         pop     bx                      ;restore intialization byte
  273.         mov     al, bl
  274.         out     dx, al                  ;send byte
  275.  
  276.         mov     dx, 00001h
  277.         mov     ax, 0C200h              ;baud constant
  278.         pop     cx                      ;restore baud
  279.         div     cx                      ;divide
  280.  
  281.         mov     dx, [di + _COM_DIVLSB]  ;low divisor port
  282.         out     dx, al                  ;send low byte
  283.         mov     dx, [di + _COM_DIVMSB]  ;high divisor port
  284.         mov     al, ah
  285.         out     dx, al                  ;send high byte
  286.  
  287.         mov     dx, [di + _COM_LINECTL] ;line control port
  288.         mov     al, bl
  289.         xor     al, _COM_DIVLATCH       ;clear flag
  290.         out     dx, al                  ;send init byte again
  291.  
  292. ;--- get interrupt vector
  293.  
  294.         mov     al, 12                  ;base interrupt
  295.         sub     al, [di + _COM_PORT]    ;subtract port number
  296.         inc     al
  297.         mov     [di + _COM_INTNUM], al  ;save it
  298.  
  299. ;--- save current old handler address
  300.  
  301.         push    es
  302.         mov     ah, 35H                 ;get vector function
  303.         mov     al, [di+_COM_INTNUM]    ;vector to get
  304.         int     21H                     ;execute
  305.         mov     [di+_COM_INTOLD], bx    ;save offset
  306.         mov     [di+_COM_INTOLD+2], es  ;save segment
  307.         pop     es
  308.  
  309. ;--- hook new interrupt
  310.  
  311.         mov     dx, OFFSET _Com_Int0C   ;interrupt 12
  312.         mov     bx, OFFSET _com_data0C  ;data address variable
  313.         cmp     BYTE [di+_COM_INTNUM],12 ;check if 12
  314.         je      _cmopn1
  315.         mov     dx, OFFSET _Com_Int0B   ;interrupt 11
  316.         mov     bx, OFFSET _com_data0B  ;data address variable
  317.  
  318. _cmopn1 mov     [bx], di                ;
  319.         push    ds                      ;-- save data address
  320.         pop     WORD [bx + 2]           ;
  321.  
  322.         mov     ah, 25H                 ;set vector function
  323.         mov     al, [di + _COM_INTNUM]  ;vector to set
  324.         int     21H                     ;execute
  325.  
  326. ;--- activate modem
  327.  
  328.         mov     dx, [di + _COM_MODEMCTL]                ;modem control port
  329.         in      al, dx                                  ;get byte
  330.         or      al, _COM_DTR OR _COM_RTS OR _COM_OUT2   ;set bits
  331.         out     dx, al                                  ;send byte
  332.  
  333. ;--- enable interrupt
  334.  
  335.         mov     cl, 4                   ;base IRQ
  336.         sub     cl, [di + _COM_PORT]
  337.         inc     cl
  338.         mov     al, 1
  339.         shl     al, cl                  ;interrupt mask bit
  340.         mov     [di + _COM_INTMSK], al  ;save it
  341.         mov     ah, al
  342.  
  343.         mov     dx, _COM_PIC01          ;interrupt enable port
  344.         in      al, dx                  ;get byte
  345.         not     ah
  346.         and     al, ah                  ;clear disable bit
  347.         out     dx, al                  ;send byte
  348.  
  349.         mov     dx, [di+_COM_INTENABLE] ;modem interrupt enable port
  350.         mov     al, _COM_DATAREADY      ;data ready
  351.         out     dx, al                  ;send byte
  352.  
  353.         mov     al, _COM_EOI            ;end of interrupt
  354.         out     _COM_PIC00, al          ;send to controller
  355.  
  356. ;--- flush interrupts
  357.  
  358.         mov     dx, [di + _COM_RXDATA]
  359.         in      al, dx
  360.         mov     dx, [di + _COM_INTIDENT]
  361.         in      al, dx
  362.         mov     dx, [di + _COM_LINESTAT]
  363.         in      al, dx
  364.         mov     dx, [di + _COM_MODEMSTAT]
  365.         in      al, dx
  366.  
  367.         pop     di
  368.         ret
  369.         ENDP
  370.  
  371. ;========================================
  372. ; Close communications port.
  373. ;
  374. ; In: BX= record address.
  375.  
  376. ComClo  PROC    NEAR
  377.  
  378. ;--- clear modem control bits
  379.  
  380.         mov     dx, [bx + _COM_MODEMCTL]        ;modem control port
  381.         in      al, dx                          ;get byte
  382.         and     al, NOT (_COM_DTR OR _COM_RTS OR _COM_OUT2) ;clear bits
  383.         out     dx, al                          ;send byte
  384.  
  385. ;--- disable interrupt
  386.  
  387.         mov     dx, _COM_PIC01          ;interrupt enable port
  388.         in      al, dx                  ;get byte
  389.         or      al, [bx + _COM_INTMSK]  ;set disable bit
  390.         out     dx, al                  ;send byte
  391.  
  392. ;--- unhook interrupt
  393.  
  394.         push    ds
  395.         mov     ah, 25H                 ;set vector function
  396.         mov     al, [bx + _COM_INTNUM]  ;vector to set
  397.         lds     dx, [bx + _COM_INTOLD]  ;old interrupt address
  398.         int     21H                     ;execute
  399.         pop     ds
  400.  
  401.         ret
  402.         ENDP
  403.  
  404. ;========================================
  405. ; Clear input buffer.
  406. ;
  407. ; In: BX= record address.
  408.  
  409. ComClr  PROC    NEAR
  410.         cli
  411.         mov     ax, [bx + _COM_BUFBEG]          ;offset
  412.         mov     [bx + _COM_BUFPTR1], ax
  413.         mov     [bx + _COM_BUFPTR2], ax
  414.         mov     ax, [bx + _COM_BUFBEG + 2]      ;segment
  415.         mov     [bx + _COM_BUFPTR1 + 2], ax
  416.         mov     [bx + _COM_BUFPTR2 + 2], ax
  417.         mov     WORD [bx + _COM_BUFBYTE], 0     ;zero bytes in buffer
  418.         sti
  419.         ret
  420.         ENDP
  421.  
  422. ;========================================
  423. ; Return bytes in receive buffer.
  424. ;
  425. ; In: BX= record address.
  426. ;
  427. ; Out: AX= byte count.
  428.  
  429. ComByt  PROC    NEAR
  430.         mov     ax, [bx + _COM_BUFBYTE] ;return bytes
  431.         ret
  432.         ENDP
  433.  
  434. ;========================================
  435. ; Input a byte.
  436. ;
  437. ; In: BX= record address.
  438. ;
  439. ; Out: AL= byte received; CY= set if
  440. ;      unavailable.
  441.  
  442. ComGet  PROC    NEAR
  443.         cmp     WORD [bx + _COM_BUFBYTE], 0     ;check if any bytes in buffer
  444.         jz      _cmget2                         ;jump if not
  445.  
  446.         push    si
  447.         push    es
  448.         les     si, [bx + _COM_BUFPTR2] ;buffer read address
  449.         cmp     si, [bx + _COM_BUFEND]  ;check if at end
  450.         jne     _cmget1
  451.         mov     si, [bx + _COM_BUFBEG]  ;wrap to start
  452. _cmget1 seg     es
  453.         mov     al, [si]                ;load byte
  454.         inc     si
  455.         mov     [bx + _COM_BUFPTR2], si ;save address
  456.         dec     WORD [bx+_COM_BUFBYTE]  ;increment bytes
  457.         pop     es
  458.         pop     si
  459.         clc
  460.         ret
  461.  
  462. ;--- no byte available
  463.  
  464. _cmget2 stc
  465.         ret
  466.         ENDP
  467.  
  468. ;========================================
  469. ; Output a byte. Will wait indefinitely
  470. ; for trasmit ready.
  471. ;
  472. ; In: AL= byte to send; BX= record
  473. ;     address.
  474.  
  475. ComPut  PROC    NEAR
  476.         mov     cx, ax          ;save byte in CX
  477.  
  478. ;--- wait for transmit ready
  479.  
  480. _cmput1 mov     dx, [bx+_COM_LINESTAT]  ;line status port
  481.         in      al, dx                  ;get byte
  482.         test    al, _COM_XMITREADY      ;check if ready to transmit
  483.         jz      _cmput1                 ;loop back if not
  484.  
  485. ;--- send byte
  486.  
  487.         mov     dx, [bx + _COM_TXDATA]  ;transmit data port
  488.         mov     al, cl                  ;byte
  489.         out     dx, al                  ;send byte
  490.         ret
  491.         ENDP
  492.  
  493. _serial1_end
  494.